﻿using System;
using System.Collections.Generic;
using System.Text;
using ZhCun.Framework.DataAccess.DbHelper;
using System.Data.Common;
using ZhCun.Framework.Common.Exceptions;
using System.Data;
using ZhCun.Framework.Common.Models.ProcedureModel;

namespace ZhCun.Framework.DataAccess.DAL
{
    public abstract class DALCommonBase
    {
        #region 抽象方法,由具体数据类实现

        /// <summary>
        /// 访问数据的DBHelper对象
        /// </summary>
        protected internal abstract IDbHelper DBHelper { get; } //子类实现        
        /// <summary>
        /// 获得数据参数对象
        /// </summary>
        protected internal abstract DbParameter GetDbParam(string paramName, object paramValue);

        /// <summary>
        /// 返回SQL参数查询.
        /// Key如果不包含参数的@符号,则加上
        /// </summary>
        protected virtual DbParameter[] GetDbParam(Dictionary<string, object> dbParamsDict)
        {
            if (dbParamsDict == null || dbParamsDict.Keys.Count == 0) return null;
            List<DbParameter> paramList = new List<DbParameter>();
            foreach (var item in dbParamsDict.Keys)
            {
                string pName = item;
                if (item.Trim().Substring(0, 1) != "@")
                {
                    pName = "@" + pName;
                }
                paramList.Add(GetDbParam(item, dbParamsDict[item]));
            }
            return paramList.ToArray();
        }

        #endregion

        //事务的缓存,列表,静态是为了让多个事务在一个对象里,多个dal访问的是一个事务缓存
        static Dictionary<Guid, Dictionary<string, Dictionary<string, object>>> _TransCacheDict;
        void AddTran(Guid tranId, string sqlText, Dictionary<string, object> dbParam)
        {
            if (tranId == Guid.Empty) return;

            if (_TransCacheDict == null)
            {
                _TransCacheDict = new Dictionary<Guid, Dictionary<string, Dictionary<string, object>>>();
                var transIdDict = new Dictionary<string, Dictionary<string, object>>();
                transIdDict.Add(sqlText, dbParam);
                _TransCacheDict.Add(tranId, transIdDict);
            }
            else
            {
                if (_TransCacheDict.ContainsKey(tranId))
                {
                    while (_TransCacheDict[tranId].ContainsKey(sqlText))
                    {
                        //如果字典Key中包含sqlText,则一直循环加入空格
                        sqlText = sqlText + " ";
                    }
                    _TransCacheDict[tranId].Add(sqlText, dbParam);
                }
                else
                {
                    var transIdDict = new Dictionary<string, Dictionary<string, object>>();
                    transIdDict.Add(sqlText, dbParam);
                    _TransCacheDict.Add(tranId, transIdDict);
                }
            }
        }
        
        public int ExecuteBySQL(Guid tranId, string sqlText, Dictionary<string, object> dbParams)
        {
            int rows;
            if (tranId != Guid.Empty)
            {
                AddTran(tranId, sqlText, dbParams);
                rows = 1;
            }
            else
            {
                //执行sql语句的操作都由此方法实现
                DbParameter[] parameters = GetDbParam(dbParams);
                rows = DBHelper.ExecNonQuery(sqlText, parameters);
            }
            return rows;
        }
        public int ExecuteBySQL(string sqlText, Dictionary<string, object> dbParams)
        {
            return ExecuteBySQL(Guid.Empty, sqlText, dbParams);
        }
        
        public virtual DataTable GetDataTableBySQL(string sqlText, Dictionary<string, object> dbParams)
        {
            DbParameter[] param = GetDbParam(dbParams);
            DataTable dt = DBHelper.GetDataTable(sqlText, param);
            return dt;
        }
        public virtual DbDataReader GetDataReaderBySQL(string sqlText, Dictionary<string, object> dbParams)
        {
            DbParameter[] param = GetDbParam(dbParams);
            DbDataReader reader = DBHelper.GetDataReader(sqlText, param);
            return reader;
        }

        #region 执行存储过程

        public virtual int ExecProcedureGetNon(ProcedureObjBase procObj)
        {
            string procName = procObj.ToString();
            Dictionary<string, object> procParam = procObj.GetProcParamObj();
            DbParameter[] param = GetDbParam(procParam);
            procObj.SetOutParam(ref param);
            int r = DBHelper.ExecNonQuery(procName, CommandType.StoredProcedure, param);
            procObj.SetOutParamValue(param);
            return r;
        }
        public virtual DataTable ExecProcedureGetDataTable(ProcedureObjBase procObj)
        {
            string procName = procObj.ToString();
            Dictionary<string, object> procParam = procObj.GetProcParamObj();
            DbParameter[] param = GetDbParam(procParam);
            procObj.SetOutParam(ref param);
            DataTable r = DBHelper.GetDataTable(procName, CommandType.StoredProcedure, param);
            procObj.SetOutParamValue(param);
            return r;
        }
        public virtual object ExecProcedureGetObj(ProcedureObjBase procObj)
        {
            string procName = procObj.ToString();
            Dictionary<string, object> procParam = procObj.GetProcParamObj();
            DbParameter[] param = GetDbParam(procParam);
            procObj.SetOutParam(ref param);
            object r = DBHelper.GetScalar(procName, CommandType.StoredProcedure, param);
            procObj.SetOutParamValue(param);
            return r;
        }

        #endregion
    }
}
